<?php

/**
 * Created by PhpStorm.
 * User: 670518964@qq.com
 * Date: 2017/10/22 0022
 * Time: 下午 8:53
 */
class Hook
{
    private $hookList;

    private $errorMsg;//错误信息
    private $errorInfo = array(
        'HOOK0000' => '钩子已经存在！！',
        'HOOK0001' => '该钩子不存在！！',
        'HOOK0010' => '该钩子中不存在回调函数！！',
    );//错误目录

    /**
     * Hook constructor. 初始化方法
     */
    function __construct()
    {
        $this->hookList = &$GLOBALS['hookList'];
        if (!isset($this->hookList)) $this->hookList = array();
    }

    /**
     * 添加一个钩子（这里的设计是钩子新增跟放置分离）
     * @param string $hook_name 钩子的名称
     * @return bool 返回boolean
     */
    function addHook($hook_name)
    {
        try {
            if (isset($this->hookList[$hook_name])) throw new Exception($this->errorInfo['HOOK0000']);
            $this->hookList[$hook_name] = array(
                'hook_name' => $hook_name,
                'call_back_func' => array()
            );
            return true;
        } catch (Exception $error) {
            $this->errorMsg = $error->getMessage();
            return false;
        }
    }

    /**
     * 新增回调操作
     * @param String $hook_name 钩子的名称
     * @param String $function 方法的名称
     * @param array $param_arr 方法的参数
     * @return bool 返回添加结果true/false
     */
    function addCallBack($hook_name, $function, array $param_arr = array())
    {
        try {
            if (!is_array($this->hookList[$hook_name])) throw new Exception($this->errorInfo['HOOK0001']);
            $this->hookList[$hook_name]['call_back_func'][] = array(
                'function_name' => $function,
                'param_arr' => $param_arr
            );
            return true;
        } catch (Exception $error) {
            $this->errorMsg = $error->getMessage();
            return false;
        }
    }

    /**
     * 放置钩子，执行钩子的地方
     * @param string $hook_name 钩子的名称
     * @param null $params 可选的外部参数
     * @return bool 返回执行结果
     */
    function runHook($hook_name, $params = null)
    {
        try {
            $hooks = $this->_getHook($hook_name);
            if (!$hooks) throw new Exception($this->errorInfo['HOOK0001']);
            if (sizeof($hooks['call_back_func']) <= 0) throw new Exception($this->errorInfo['HOOK0010']);

            foreach ($hooks['call_back_func'] as $key => &$value) {
                $param = $value['param_arr'];
                if (isset($params)) {
                    if (is_array($params)) {
                        $param = array_merge($param, $params);
                    } else {
                        array_push($param, $params);
                    }
                }

                call_user_func_array($value['function_name'], $param);
            };

            return true;
        } catch (Exception $error) {
            $this->errorMsg = $error->getMessage();
            return false;
        }
    }

    /**
     * 删除一个钩子
     * @param String $hook_name 钩子的名称
     * @return bool 返回成功
     */
    function delHook($hook_name)
    {
        unset($this->hookList[$hook_name]);
        return true;
    }

    /**
     * 返回错误信息
     * @return mixed
     */
    function getErrorMsg()
    {
        return $this->errorMsg;
    }


    /**
     * 加上一层可以做排序处理等的升级，这里是为了以后升级做出的另外的封装操作
     * @param $hook_name
     * @return mixed
     */
    private function _getHook($hook_name)
    {
        return isset($this->hookList[$hook_name]) ? $this->hookList[$hook_name] : false;
    }
}